﻿using System.Windows.Forms;
using CloudShot.Entities;

namespace CloudShot.Controls
{
  internal class HotkeyBox : TextBox
  {
    private const int WM_KEYDOWN = 0x100;
    private const int WM_KEYUP = 0x101;
    private const int WM_SYSKEYDOWN = 0x104;
    private const int WM_SYSKEYUP = 0x105;

    private bool _keySetted;
    private Hotkey _hotkey;

    public override string Text
    {
      get { return base.Text; }
      set
      {
        base.Text = value;
        Hotkey.TryParse(value, out _hotkey);
      }
    }

    public Hotkey Hotkey
    {
      get { return _hotkey; }
      set
      {
        _hotkey = value;
        base.Text = _hotkey.ToString();
      }
    }

    //TODO: refactor, code is too hacky
    protected override bool ProcessKeyEventArgs(ref Message msg)
    {
      bool isKeyUp = msg.Msg == WM_KEYUP || msg.Msg == WM_SYSKEYUP;
      bool isKeyDown = msg.Msg == WM_KEYDOWN || msg.Msg == WM_SYSKEYDOWN;
      Keys key = (Keys)(int)msg.WParam & Keys.KeyCode;

      if (IsModifier(key) || IsIgnored(key))
      {
        key = Keys.None;
      }

      if (isKeyDown)
      {
        Hotkey = Hotkey.Empty;
        _keySetted = false;
      }
      else if (isKeyUp)//PrintScreen key comes only on KeyUp =(
      {
        if (!_keySetted)
          Hotkey = Hotkey.Empty;

        if (key != Keys.None)
          _keySetted = false;
      }

      if (!_keySetted)
      {
        Hotkey = new Hotkey(key, GetKeyModifiers());
      }

      if (key != Keys.None)
      {
        _keySetted = true;
      }

      //Debug.WriteLine("### : " + modifiersText + keyName + " ks:" + _keySetted);

      return base.ProcessKeyEventArgs(ref msg);
    }

    private static bool IsIgnored(Keys key)
    {
      return key == Keys.Delete || key == Keys.Back;
    }

    private static bool IsModifier(Keys key)
    {
      return key == Keys.Menu || key == Keys.ControlKey || key == Keys.ShiftKey;
    }

    private static KeyModifiers GetKeyModifiers()
    {
      var result = KeyModifiers.None;

      if ((ModifierKeys & Keys.Control) == Keys.Control)
        result |= KeyModifiers.Ctrl;

      if ((ModifierKeys & Keys.Shift) == Keys.Shift)
        result |= KeyModifiers.Shift;

      if ((ModifierKeys & Keys.Alt) == Keys.Alt)
        result |= KeyModifiers.Alt;

      return result;
    }
  }
}